# -*- coding: utf-8 -*-
import stackless, glob, re, sys, random, numpy, numpy.random, os, pickle, string, urllib, struct, time
import stacklesssocket
stacklesssocket.install();
import socket
from string import *
from math import *
from ctypes import *
from pyparsing import *
import libcerebra as cerebra
class server:
	pgm=[]
	networks=[]
	vtable={}
	def __init__(self, maxsockets, next=None):
			self.conn=[]
			self.maxsockets=maxsockets
			self.s = socket.socket(socket.AF_TIPC, socket.SOCK_STREAM,0)
			self.addr=self.s.getsockname()
			print "Bound to", self.addr
			NODE=self.addr[1]
			PORT=self.addr[2]
			self.NODE=NODE
			self.PORT=PORT
			stackless.tasklet(self.route)()
	def route(self):
			stackless.schedule()
			i=1
			while 1:
				try:
					
					addr=self.s.recvfrom(1024)[1]
				except:
					pass
				Sleep(5.0)
				stackless.schedule()
				if(i<self.maxsockets):
						s2=socket.socket(socket.AF_TIPC, socket.SOCK_STREAM,0)
						self.conn.append((s2, addr))
						s2.sendto(str(s2.getsockname()[2]),addr)
						print 'Connected by', addr
						stackless.tasklet(self.inbound)(i-1)
						i+=1
				elif self.next!=None:
						socket.socket(socket.AF_TIPC, socket.SOCK_STREAM,0).sendto(addr, self.next)
	def evolve(i):
		while(1):
				stackless.schedule()
				self.queue["evolve"]=1
				print "%i node: executing GPU-accelerated convergence mapping for timestep %f..."%(i, self.networks[i].dt)
				self.networks[i].evolve(c_float(self.networks[i].dt).value, c_int(6000).value)
				print "...%i frames executed."%(6)
				del self.queue["evolve"]
	def run(i, *args):
		stackless.schedule()
		self.conn[i][0].sendto(i(*args), address=self.conn[i][1])
	def inbound(self,i):
		stackless.schedule()
		while 1:
				stackless.schedule()
				data = self.conn.recvfrom(1000)[0]
				if not data: break
				elif data.split(" ")[0]=="lambda":
					self.pgm.append(eval(data))
				else:
					if data=="init":
						n=cerebra.network()
						input=numpy.array(self.conn[i][0].recvfrom((1024*1024*65*4+1024*4)*2)[0].split(' ')).astype(int)
						n.d=self.conn[i][0].recvfrom(256)[0]
						n.dt=self.conn[i][0].recvfrom(1000)[0]
						cerebra.initialize(n.return_this(), input, spectrum, numpy.ones(1024*1024*65+1024))
						self.networks[self.conn[i].recvfrom(1000)[0]]=n
						stackless.tasklet(self.evolve)(data[6])
					elif data[0]!="recv":
						stackless.tasklet(self.run)(i, args)
					else:
						self.output=numpy.empty(1024*1024*64+1024*1024+1024, dtype=numpy.float32)
						cerebra.save(self.network[data[1]].return_this(), self.output)
						self.conn[i][0].sendto(string.join(self.output.tolist(),' '), address=self.conn[i][1])
	

	
sleepingTasklets = []

def Sleep(secondsToWait):
	    channel = stackless.channel()
	    endTime = time.time() + secondsToWait
	    sleepingTasklets.append((endTime, channel))
	    sleepingTasklets.sort()
	    # Block until we get sent an awakening notification.
	    channel.receive()

def ManageSleepingTasklets():
	    while 1:
	        if len(sleepingTasklets):
	            endTime = sleepingTasklets[0][0]
	            if endTime <= time.time():
	                channel = sleepingTasklets[0][1]
	                del sleepingTasklets[0]
	                # We have to send something, but it doesn't matter what as it is not used.
	                channel.send(None)
	        stackless.schedule()
if __name__=="__main__":
	stackless.tasklet(ManageSleepingTasklets)()
	server(sys.argv[1])
	while stackless.getruncount() > 1:
		t = stackless.run(100000)
		if t:
			t.insert()
					
					
					
			
	
